﻿using BootstrapBlazor.Components;
using LaserMark.Models;
using LaserMark.Control.Service;
using LaserMark.View.Services;
using System.Windows.Media;

namespace LaserMark.Extensions
{
    public static class ScanPointExtension
    {
        /// <summary>
        ///
        /// </summary>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="axisX"></param>
        /// <param name="axisY"></param>
        /// <param name="yPluseMM"></param>
        /// <param name="xPluseMM"></param>
        /// <param name="scanVel"></param>
        /// <param name="setting"></param>
        /// <param name="control"></param>
        /// <returns></returns>
        public static async Task<Tuple<string, double, double, double, double, double, bool>> Scan(int width, int height, MarkOption option, IControl control, CancellationTokenSource source)
        {
            double offsetX = 0;
            double offsetX1 = 0;
            double offsetY = 0;

            double pOffsetX = 0;
            double pOffsetX1 = 0;
            double pOffsetY = 0;
            double pOffsetY1 = 0;

            double degress = 0;
            //第一段Y轴走的距离
            var pluseY1 = (int)((height * (30 / (double)100)) / option.YPluse.Value);
            //第二段段Y轴走的距离
            var pluseY = (int)((height * (option.PhotoelectricitySetting.ScanSinglePoint / (double)100)) / option.YPluse.Value);


            // X 轴百分之30的位置
            var pluseX1 = (int)(width * (option.PhotoelectricitySetting.ScanPoint1 / (double)100) / option.XPluse.Value);
            // X 轴百分之80的位置
            var pluseX2 = (int)(width * (option.PhotoelectricitySetting.ScanPoint2 / (double)100) / option.XPluse.Value);
            var ret = new Tuple<string, double, double, double, double, double, bool>("", 0, 0, 0, 0, 0, false);

            // 默认四点
            mc.GT_GetTrapPrm(0, (short)option.AxisCode.X, out mc.TTrapPrm trapPrm);
            trapPrm.acc = option.ScanAcc.X / 10000;
            trapPrm.dec = option.ScanDec.X / 10000;
            trapPrm.smoothTime = 20;
            await control.SetPTP(0, (short)option.AxisCode.Y, (int)option.ScanVel.Y, pluseY1, ref trapPrm);
            int status;
            do
            {
                await Task.Delay(1);
                await control.GetAxisStatus(0, (short)option.AxisCode.Y, out status, 1, out _);
            }
            while ((status & 0x400) != 0 && !source.IsCancellationRequested);

            //Y轴移动到 30% 停止
            if ((status & 0x400) == 0)
            {
                await control.Stop(0, 1 << ((short)option.AxisCode.Y - 1), 0);

                // X  轴运动，找玻璃边,此处设置最大行程扫不到玻璃边后停止运动
                mc.GT_PrfJog(0, (short)option.AxisCode.X);
                mc.GT_GetJogPrm(0, (short)option.AxisCode.X, out mc.TJogPrm jogPrm);
                jogPrm.acc = 0.1;
                jogPrm.dec = 0.1;
                jogPrm.smooth = 0.9;
                mc.GT_SetJogPrm(0, (short)option.AxisCode.X, ref jogPrm);
                mc.GT_SetVel(0, (short)option.AxisCode.X, 10);
                mc.GT_Update(0, 1 << ((short)option.AxisCode.X - 1));
                int sin = 0;
                double value = 0;

                // 获取光电扫描状态
                do
                {
                    await Task.Delay(1);
                    await control.GetDi(0, mc.MC_GPI, out int val);
                    var arr = Convert.ToString(val, 2).PadLeft(16, '0').ToArray();
                    arr.Reverse();
                    if (arr[8] == '1')
                    {
                        // 获取 X 轴编码器位置
                        mc.GT_GetEncPos(0, (short)option.AxisCode.X, out value, 1, out _);
                        offsetX1 = value * option.XPluse.Value;
                        pOffsetX1 = value;
                        // 检测光电状态 停止检测
                        mc.GT_Stop(0, 1 << ((short)option.AxisCode.X - 1), 0);
                        sin = 1;
                    }

                    // 获取 X 轴编码器位置
                    mc.GT_GetEncPos(0, (short)option.AxisCode.X, out double maxValue, 1, out _);
                    if (maxValue >= (option.PhotoelectricitySetting.ScanMaxX / option.XPluse.Value))
                    {
                        mc.GT_Stop(0, 1 << (2 - 1), 0);
                        return new Tuple<string, double, double, double, double, double, bool>("超出 X 最大行程", 0, 0, 0, 0, 0, false);
                    }
                }
                while (sin != 1 && !source.IsCancellationRequested);
            }

            do
            {
                await Task.Delay(1);
                await control.GetAxisStatus(0, (short)option.AxisCode.X, out status, 1, out _);
            }
            while ((status & 0x400) != 0 && !source.IsCancellationRequested);

            await control.SetPTP(0, (short)option.AxisCode.X, (int)option.ScanVel.X, 0, ref trapPrm);

            do
            {
                await Task.Delay(1);
                await control.GetAxisStatus(0, (short)option.AxisCode.X, out status, 1, out _);
            }
            while ((status & 0x400) != 0 && !source.IsCancellationRequested);


            // Y 轴扫描第一个点
            mc.GT_GetTrapPrm(0, (short)option.AxisCode.X, out trapPrm);
            trapPrm.acc = option.ScanAcc.X / 10000;
            trapPrm.dec = option.ScanDec.X / 10000;
            trapPrm.smoothTime = 20;
            await control.SetPTP(0, (short)option.AxisCode.Y, (int)option.ScanVel.Y, pluseY, ref trapPrm);
            do
            {
                await Task.Delay(10);
                await control.GetAxisStatus(0, (short)option.AxisCode.Y, out status, 1, out _);
            }
            while ((status & 0x400) != 0 && !source.IsCancellationRequested);

            //Y轴移动到 50% 停止
            if ((status & 0x400) == 0)
            {
                await control.Stop(0, 1 << ((short)option.AxisCode.Y - 1), 0);

                // X  轴运动，找玻璃边,此处设置最大行程扫不到玻璃边后停止运动
                mc.GT_PrfJog(0, (short)option.AxisCode.X);
                mc.GT_GetJogPrm(0, (short)option.AxisCode.X, out mc.TJogPrm jogPrm);
                jogPrm.acc = 0.1;
                jogPrm.dec = 0.1;
                jogPrm.smooth = 0.9;
                mc.GT_SetJogPrm(0, (short)option.AxisCode.X, ref jogPrm);
                mc.GT_SetVel(0, (short)option.AxisCode.X, 10);
                mc.GT_Update(0, 1 << ((short)option.AxisCode.X - 1));
                int sin = 0;
                double value = 0;

                // 获取光电扫描状态
                do
                {
                    await Task.Delay(1);
                    await control.GetDi(0, mc.MC_GPI, out int val);
                    var arr = Convert.ToString(val, 2).PadLeft(16, '0').ToArray();
                    arr.Reverse();
                    if (arr[8] == '1')
                    {
                        // 获取 X 轴编码器位置
                        mc.GT_GetEncPos(0, (short)option.AxisCode.X, out value, 1, out _);
                        offsetX = value * option.XPluse.Value;
                        pOffsetX = value;
                        // 检测光电状态 停止检测
                        mc.GT_Stop(0, 1 << ((short)option.AxisCode.X - 1), 0);
                        sin = 1;
                    }

                    // 获取 X 轴编码器位置
                    mc.GT_GetEncPos(0, (short)option.AxisCode.X, out double maxValue, 1, out _);
                    if (maxValue >= (option.PhotoelectricitySetting.ScanMaxX / option.XPluse.Value))
                    {
                        mc.GT_Stop(0, 1 << (2 - 1), 0);
                        return new Tuple<string, double, double, double, double, double, bool>("超出 X 最大行程", 0, 0, 0, 0, 0, false);
                    }
                }
                while (sin != 1 && !source.IsCancellationRequested);

                await control.SetPTP(0, (short)option.AxisCode.Y, (int)option.ScanVel.Y, 0, ref trapPrm);
                Thread.Sleep(300);

                //X 轴向前移动到 30% 的位置 (0,pluseX1 - (int)value)  (value1,pluseX1 - (int)value)
                trapPrm.acc = option.ScanAcc.X / 10000;
                trapPrm.dec = option.ScanDec.X / 10000;
                trapPrm.smoothTime = 20;
                await control.SetPTP(0, (short)option.AxisCode.X, (int)option.ScanVel.X, pluseX1 + (int)value, ref trapPrm);
                int status2;
                do
                {
                    await Task.Delay(10);
                    // 检测 X Y轴 是否停止运动
                    mc.GT_GetSts(0, (short)option.AxisCode.X, out status, 1, out _);
                }
                while ((status & 0x400) != 0 && !source.IsCancellationRequested);

                do
                {
                    await Task.Delay(10);
                    // 检测 Y轴 是否停止运动
                    mc.GT_GetSts(0, (short)option.AxisCode.Y, out status2, 1, out _);
                }
                while ((status2 & 0x400) != 0 && !source.IsCancellationRequested);

                // 当 X Y 轴停止运动时，开启找边运动，此处设置最大行程扫不到玻璃边后停止运动
                if ((status & 0x400) == 0 && (status2 & 0x400) == 0)
                {
                    jogPrm.acc = 0.1;
                    jogPrm.dec = 0.1;
                    jogPrm.smooth = 0.9;
                    await control.SetPrfJog(0, (short)option.AxisCode.Y, 3, ref jogPrm);
                    double value1 = 0;
                    // 获取光电扫描状态
                    int sin2 = 0;
                    do
                    {
                        await Task.Delay(1);
                        await control.GetDi(0, mc.MC_GPI, out int val);
                        var arr = Convert.ToString(val, 2).PadLeft(16, '0').ToArray();
                        arr.Reverse();
                        if (arr[8] == '1')
                        {
                            // 获取 Y1 轴编码器位置
                            mc.GT_GetEncPos(0, (short)option.AxisCode.Y, out value1, 1, out _);
                            pOffsetY = value1;
                            sin2 = 1;
                        }

                        // 获取 Y1 轴编码器位置
                        mc.GT_GetEncPos(0, (short)option.AxisCode.Y, out double maxValue1, 1, out _);
                        if (maxValue1 >= (option.PhotoelectricitySetting.ScanMaxY / option.YPluse.Value))
                        {
                            mc.GT_Stop(0, 1 << ((short)option.AxisCode.Y - 1), 0);
                            return new Tuple<string, double, double, double, double, double, bool>("超出 Y 最大行程", 0, 0, 0, 0, 0, false);
                        }
                    }
                    while (sin2 != 1 && !source.IsCancellationRequested);

                    if (sin2 == 1)
                    {
                        // 检测光电状态 停止检测
                        mc.GT_Stop(0, 1 << ((short)option.AxisCode.Y - 1), 0);
                        Thread.Sleep(300);
                        trapPrm.acc = option.ScanAcc.Y / 10000;
                        trapPrm.dec = option.ScanDec.Y / 10000;
                        trapPrm.smoothTime = 20;
                        await control.SetPTP(0, (short)option.AxisCode.Y, (int)option.ScanVel.Y, 0, ref trapPrm);
                    }

                    // X轴移动到 80% 的位置(value2,pluseX3 - (int)value)
                    trapPrm.acc = option.ScanAcc.X / 10000;
                    trapPrm.dec = option.ScanDec.X / 10000;
                    trapPrm.smoothTime = 20;
                    await control.SetPTP(0, (short)option.AxisCode.X, (int)option.ScanVel.X, pluseX2, ref trapPrm);

                    int status3;
                    do
                    {
                        await Task.Delay(1);
                        // 检测 X 轴 是否停止运动
                        mc.GT_GetSts(0, (short)option.AxisCode.X, out status, 1, out _);
                    }
                    while ((status & 0x400) != 0 && !source.IsCancellationRequested);

                    do
                    {
                        await Task.Delay(1);
                        // 检测 Y轴 是否停止运动
                        mc.GT_GetSts(0, (short)option.AxisCode.Y, out status3, 1, out _);
                    }
                    while ((status3 & 0x400) != 0 && !source.IsCancellationRequested);

                    // 当 X Y 轴停止运动时，开启找边运动，此处设置最大行程扫不到玻璃边后停止运动
                    if ((status & 0x400) == 0 && (status3 & 0x400) == 0)
                    {
                        jogPrm.acc = 0.1;
                        jogPrm.dec = 0.1;
                        jogPrm.smooth = 0.9;
                        await control.SetPrfJog(0, (short)option.AxisCode.Y, 3, ref jogPrm);
                        double value2 = 0;
                        // 获取光电扫描状态
                        int sin3 = 0;
                        do
                        {
                            await Task.Delay(1);
                            await control.GetDi(0, mc.MC_GPI, out int val);
                            var arr = Convert.ToString(val, 2).PadLeft(16, '0').ToArray();
                            arr.Reverse();
                            if (arr[8] == '1')
                            {
                                // 获取 Y1 轴编码器位置
                                mc.GT_GetEncPos(0, (short)option.AxisCode.Y, out value2, 1, out _);
                                // 检测光电状态 停止检测
                                mc.GT_Stop(0, 1 << ((short)option.AxisCode.Y - 1), 0);
                                pOffsetY1 = value2;

                                var deg = AngleExtension.GetAngle(
                                    new Models.Point()
                                    {
                                        X = value2 / option.YPluse.Value,
                                        Y = pluseX2 / option.XPluse.Value
                                    },
                                    new Models.Point()
                                    {
                                        X = value1 / option.YPluse.Value,
                                        Y = pluseX1 / option.XPluse.Value
                                    });

                                if (deg.angle < 0)
                                {
                                    degress = deg.rad + 1.5707963267948966;
                                    if (90 + deg.angle > 3)
                                    {
                                        mc.GT_Stop(0, (short)option.AxisCode.X, 0);
                                        return new Tuple<string, double, double, double, double, double, bool>("顺时针偏差", 0, 0, 0, 0, 0, false);
                                    }
                                    degress = -degress;
                                }

                                if (deg.angle > 0)
                                {
                                    degress = 1.5707963267948966 - deg.rad;
                                    if (90 - deg.angle > 3)
                                    {
                                        mc.GT_Stop(0, (short)option.AxisCode.X, 0);
                                        return new Tuple<string, double, double, double, double, double, bool>("逆时针偏差", 0, 0, 0, 0, 0, false);
                                    }
                                }

                                offsetY = value2 * option.YPluse.Value;
                                pOffsetY = value2;
                                sin3 = 1;

                                var aa = CrossPointExtension.Intersection(new[] { pOffsetX, pluseY }, new[] { pOffsetX1, pluseY1 }, new[] { pluseX2, value2 }, new[] { pluseX1, value1 });
                                offsetX = aa[0];
                                offsetY = aa[1];
                            }

                            // 获取 Y1 轴编码器位置
                            mc.GT_GetEncPos(0, (short)option.AxisCode.Y, out double maxValue2, 1, out _);
                            if (maxValue2 >= (option.PhotoelectricitySetting.ScanMaxY / option.YPluse.Value))
                            {
                                mc.GT_Stop(0, 1 << ((short)option.AxisCode.Y - 1), 0);

                                return new Tuple<string, double, double, double, double, double, bool>("超出 Y 最大行程", 0, 0, 0, 0, 0, false);
                            }
                        }
                        while (sin3 != 1 && !source.IsCancellationRequested);
                    }
                }
            }

            int statusend;
            int status2end;
            do
            {
                await Task.Delay(10);
                // 检测 X Y轴 是否停止运动
                mc.GT_GetSts(0, (short)option.AxisCode.X, out statusend, 1, out _);
            }
            while ((statusend & 0x400) != 0 && !source.IsCancellationRequested);

            do
            {
                await Task.Delay(10);
                // 检测 Y轴 是否停止运动
                mc.GT_GetSts(0, (short)option.AxisCode.Y, out status2end, 1, out _);
            }
            while ((status2end & 0x400) != 0 && !source.IsCancellationRequested);

            ret = new Tuple<string, double, double, double, double, double, bool>("扫边成功", offsetX, offsetY, pOffsetX, pOffsetY, degress, true);
            return ret;
        }
    }
}
